package com.demo.cryptology.utils;

import com.demo.cryptology.tools.Convertor;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;

public class AESUtils {
    private static final String UTF_8 = "UTF-8";
    public static final String ALGORITHM = "AES/ECB/PKCS5Padding";
    public static final String AES = "AES";

    public static byte[] encrypt(byte[] src, String password) throws Exception {
        SecretKeySpec keySpec = getSecretKeySpec(password);
        //创建一个密钥工厂，然后用它把DESKeySpec转换成
        //cipher对象世纪完成加密操作
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        //用密钥初始化cipher对象
        cipher.init(cipher.ENCRYPT_MODE, keySpec);
        //现在，获取数据并加密
        //正式执行加密操作
        byte[] r = cipher.doFinal(src);
//        return r;
        return encoder.encode(r);
    }


    public static byte[] decrypt(byte[] src, String password) throws Exception {
        src = decoder.decode(src);
        SecretKeySpec keySpec = getSecretKeySpec(password);
        //创建一个密钥工厂，然后用它把DESKeySpec转换成
        //cipher对象世纪完成加密操作
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        //用密钥初始化cipher对象
        cipher.init(cipher.DECRYPT_MODE, keySpec);
        //现在，获取数据并加密
        //正式执行加密操作
        byte[] r = cipher.doFinal(src);
        return r;
    }

    private static SecretKeySpec getSecretKeySpec(String password) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("MD5");
        byte[] bytes = password.getBytes(UTF_8);
        digest.update(bytes, 0, bytes.length);
        byte[] key = digest.digest();
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES);
        return secretKeySpec;


//        KeyGenerator kgen = KeyGenerator.getInstance(AES);
//        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
//        random.setSeed(password.getBytes(UTF_8));
//        kgen.init(128, random);
//        SecretKey secretKey = kgen.generateKey();
//        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), AES);
//        return keySpec;
    }


    static final java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
    static final java.util.Base64.Encoder encoder = Base64.getEncoder();


    /**
     * AES的加密函数
     *
     * @param str 传入需要加密的字符
     * @param key 传入一个16位长度的密钥。否则报错
     * @return 执行成功返回加密结果，否则报错
     * @throws Exception 抛出一个加密异常
     */
    public static String aesEncrypt(String str, String key) throws Exception {
        if (str == null || key == null) return null;
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), "AES"));
        byte[] bytes = cipher.doFinal(str.getBytes("utf-8"));
        return new BASE64Encoder().encode(bytes);
    }

    /**
     * AES的解密函数
     *
     * @param str 传入需要解密的字符
     * @param key 传入一个16位长度的密钥。否则报错
     * @return 执行成功返回加密结果，否则报错
     * @throws Exception 抛出一个解密异常
     */
    public static String aesDecrypt(String str, String key) throws Exception {
        if (str == null || key == null) return null;
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes("utf-8"), "AES"));
        byte[] bytes = new BASE64Decoder().decodeBuffer(str);
        bytes = cipher.doFinal(bytes);
        return new String(bytes, "utf-8");
    }


    public static void main(String[] args) throws Exception {
        String str = "123456";
        System.out.println("加密前:" + str);
        //长度是8的倍数
        String password = "123456";
        byte[] result = AESUtils.encrypt(str.getBytes(UTF_8), password);
        System.out.println("加密后:" + Convertor.bytesToHex(result));
//        System.out.println("base64加密:"+);

//        byte[] decryResult = AESUtils.decrypt(result, password);
//        System.out.println("解密后:" + new String(decryResult, UTF_8));
//        String result = aesEncrypt(str, password);
//        System.out.println(result);

    }
}
